<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Countdown Tests</title>

<script src="countdown.js" type="text/javascript"></script>
<style type="text/css">

p {
	font-family: Verdana, Geneva, sans-serif;
	font-size: 12px;
	line-height: 0px;
}

.red {
	color: #c31c00;
	font-weight:bold;
}

.sectionsep {
	border-top-width: 1px;
	border-top-style: solid;
	border-top-color: #999;
}

.nowrap {
	white-space: nowrap;
}

</style>

</head>
<body style="background-color:#EDEDED">


<table id="mytable" cellpadding="1">
  <tr>
    <td>&nbsp;</td>
    <td>years</td>
    <td>months</td>
    <td>days</td>
    <td>hours</td>
    <td>minutes</td>
    <td>seconds</td>
    <td>ok</td>
    <td>date</td>
  </tr>
</table>


<script type="application/javascript">


var timediff = new jbeeb.TimeDiff({
	rangeHi : "year",
	rangeLo : "second"
});

function makeDate(y, mo, day, h, m, s){
	//console.log(new Date(y, mo-1, day || 0, h || 0, m || 0, s || 0).toString());
	return new Date(y, mo-1, day || 0, h || 0, m || 0, s || 0);
}

function process(start, target, shouldbe){

	
	var result = timediff.diff(start, target);
	
	var mytable = document.getElementById("mytable");
	
	var tableRowResult = document.createElement("tr");
	var titleResult = document.createElement("td");
	var ty = document.createElement("td");
	var tmo = document.createElement("td");
	var td = document.createElement("td");
	var th = document.createElement("td");
	var tm = document.createElement("td");
	var ts = document.createElement("td");
	var tok = document.createElement("td");
	var tdate = document.createElement("td");
	
	tableRowResult.appendChild(titleResult).innerHTML = "result";
	tableRowResult.appendChild(ty);
	tableRowResult.appendChild(tmo);
	tableRowResult.appendChild(td);
	tableRowResult.appendChild(th);
	tableRowResult.appendChild(tm);
	tableRowResult.appendChild(ts);
	tableRowResult.appendChild(tok);
	tableRowResult.appendChild(tdate);
	
	ty.innerHTML = result.year;
	tmo.innerHTML = result.month;
	td.innerHTML = result.day;
	th.innerHTML = result.hour;
	tm.innerHTML = result.minute;
	ts.innerHTML = result.second;
	tok.innerHTML = "";
	tdate.innerHTML = "&nbsp;end: " + printDate(target);
	
	
	
	
	//---------------------------
	
	var tableRowShouldbe = document.createElement("tr");
	var titleShouldBe = document.createElement("td");
	var sy = document.createElement("td");
	var smo = document.createElement("td");
	var sd = document.createElement("td");
	var sh = document.createElement("td");
	var sm = document.createElement("td");
	var ss = document.createElement("td");
	var sok = document.createElement("td");
	var sdate = document.createElement("td");
	sdate.setAttribute("nowwrap", "nowrap");
	sdate.className = "noWrap";
	
	tableRowShouldbe.appendChild(titleShouldBe).innerHTML = "should be";
	tableRowShouldbe.appendChild(sy);
	tableRowShouldbe.appendChild(smo);
	tableRowShouldbe.appendChild(sd);
	tableRowShouldbe.appendChild(sh);
	tableRowShouldbe.appendChild(sm);
	tableRowShouldbe.appendChild(ss);
	tableRowShouldbe.appendChild(sok);
	tableRowShouldbe.appendChild(sdate);
	
	sy.className = smo.className = sd.className = sh.className = sm.className = ss.className = sok.className = sdate.className = "sectionsep";
	
	sy.innerHTML = shouldbe.y;
	smo.innerHTML = shouldbe.mo;
	sd.innerHTML = shouldbe.d;
	sh.innerHTML = shouldbe.h;
	sm.innerHTML = shouldbe.m;
	ss.innerHTML = shouldbe.s;
	sok.innerHTML = "";
	sdate.innerHTML = "start: " + printDate(start) + (shouldbe.note ? "&nbsp;&nbsp;&nbsp;&nbsp; " + shouldbe.note : "");
	
	var fail = false;
	if(parseInt(shouldbe.y) != parseInt(result.year) ) {
		ty.className = "red";
		fail = true;
	}
	if(parseInt(shouldbe.mo) != parseInt(result.month) ) {
		tmo.className = "red";
		fail = true;
	}
	if(parseInt(shouldbe.d) != parseInt(result.day) ) {
		td.className = "red";
		fail = true;
	}
	if(parseInt(shouldbe.h) != parseInt(result.hour) ) {
		th.className = "red";
		fail = true;
	}
	if(parseInt(shouldbe.m) != parseInt(result.minute) ) {
		tm.className = "red";
		fail = true;
	}
	if(parseInt(shouldbe.s) != parseInt(result.second) ) {
		ts.className = "red";
		fail = true;
	}
	
	if(fail){
		tok.className = "red";
		tok.innerHTML = "CHECK";
	}
	
	
	mytable.appendChild(tableRowShouldbe);
	mytable.appendChild(tableRowResult);
	
	
}

function printDate(Vhr){
	var ampm = Vhr.getHours() > 11 ? "pm" : "am";
	var hrs = Vhr.getHours() % 12;
	hrs = hrs == 0 ? 12 : hrs;
	return Vhr.getFullYear() + " &nbsp;&nbsp;" + (Vhr.getMonth() + 1) + "/" + Vhr.getDate() + " &nbsp;&nbsp;" + hrs + " " + ampm + " &nbsp;&nbsp; = " + Vhr.getHours() + " military ";
}



// ------------------------------------------
// > 1 year random tests
// ------------------------------------------


process(
	makeDate(2014, 1, 29),
	makeDate(2014, 3, 1),
	{y:0, mo:1, d:3, h:0, m:0, s:0, note:"one month minus 1 day"}
);

process(
	makeDate(2014, 1, 17),
	makeDate(2014, 2, 16),
	{y:0, mo:0, d:30, h:0, m:0, s:0, note:"one month minus 1 day"}
);

//NOTE: May fail due to daylight wavings time (+1 hour across the year
process(
	// 6 whole months between
	// + 16 days from June 15 to June 30 (including June 15th because it's set to 00:00 so its a whole day)
	// + 13 days of July (not including the 14th because it's set to 00:00)
	// == 29 days
	makeDate(2014, 6, 15),
	makeDate(2014, 7, 14),
	{y:0, mo:0, d:29, h:0, m:0, s:0, note:"one month minus one day spanning daylight savings"}
);




//NOTE: May fail due to daylight wavings time (+1 hour across the year
process(
	// 6 whole months between
	// + 17 days from Dec 15 to Dec 31 (including Dec 15th because it's set to 00:00 so its a whole day)
	// + 13 days of Jan (not including the 14th because it's set to 00:00)
	// == 30 days
	makeDate(2014, 6, 15),
	makeDate(2015, 1, 14),
	{y:0, mo:6, d:30, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);


process(
	// 4 whole months between
	// + 17 days from May 15 to May 31 (including may 15th because it's set to 00:00 so its a whole day)
	// + 13 days of jun (not including the 14th because it's set to 00:00)
	// == 30 days
	makeDate(2014, 1, 15),
	makeDate(2015, 6, 14),
	{y:1, mo:4, d:30, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

// ------------------------------------------
// Random spot tests
// ------------------------------------------
process(
	// 4 whole months between
	// + 17 days from May 15 to May 31 (including may 15th because it's set to 00:00 so its a whole day)
	// + 13 days of June (not including the 14th because it's set to 00:00)
	// == 30 days
	makeDate(2014, 1, 15),
	makeDate(2014, 6, 14),
	{y:0, mo:4, d:30, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	makeDate(2014, 1, 15),
	makeDate(2016, 1, 14),
	{y:1, mo:11, d:30, h:0, m:0, s:0}
);

process(
	makeDate(2014, 1, 15),
	makeDate(2015, 1, 14),
	{y:0, mo:11, d:30, h:0, m:0, s:0}
);

process(
	makeDate(2014, 3, 4),
	makeDate(2014, 3, 5),
	{y:0, mo:0, d:1, h:0, m:0, s:0}
);

process(
	makeDate(2014, 3, 4),
	makeDate(2014, 4, 5),
	{y:0, mo:1, d:1, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	makeDate(2014, 3, 4),
	makeDate(2014, 4, 4),
	{y:0, mo:1, d:0, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	makeDate(2014, 3, 4),
	makeDate(2014, 4, 3),
	{y:0, mo:0, d:30, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 3/4 -> 4/4 < 1 month
	// => 
	// + 3/4 to 3/31 = 27
	// + 4/1 to 4/3 = 2 (not including 4/3 since the date is set to 00:00 o'clock)
	// == 29 days
	// => add up hours
	// + 3/4 @ 19:00 - midnight = 5 hours.
	// + 0 (going to midnight of 4/2 or 00:00 or 4/3 however you see it.
	// == 5 horus
	makeDate(2014, 3, 4, 19),
	makeDate(2014, 4, 3),
	{y:0, mo:0, d:29, h:5, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 2 months + 2 horus
	makeDate(2014, 2, 26, 8),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:2, d:0, h:2, m:0, s:0, note:"spans daylight savings -1 hour"}
);


process(
	// 2 monts + 1 hour
	makeDate(2014, 2, 26, 9),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:2, d:0, h:1, m:0, s:0, note:"spans daylight savings -1 hour"}
);


process(
	// 2 months even
	makeDate(2014, 2, 26, 10),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:2, d:0, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 1 month 30 days + 23 hours
	makeDate(2014, 2, 26, 11),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:1, d:30, h:23, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 1 month 30 days + 22 hours
	makeDate(2014, 2, 26, 12),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:1, d:30, h:22, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 0
	makeDate(2014, 2, 28, 15),
	makeDate(2014, 2, 28, 15),
	{y:0, mo:0, d:0, h:0, m:0, s:0}
);
process(
	// 1 day
	makeDate(2014, 2, 28, 15),
	makeDate(2014, 3, 1, 15),
	{y:0, mo:0, d:1, h:0, m:0, s:0}
);
process(
	// 23 hours
	makeDate(2014, 2, 28, 15),
	makeDate(2014, 3, 1, 14),
	{y:0, mo:0, d:0, h:23, m:0, s:0}
);

process(
	// 2 months 1 hour
	makeDate(2014, 2, 26, 9),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:2, d:0, h:1, m:0, s:0, note:"spans daylight savings -1 hour"}
);
process(
	// 2 months
	makeDate(2014, 2, 26, 10),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:2, d:0, h:0, m:0, s:0, note:"spans daylight savings -1 hour"}
);

process(
	// 2/26 -> 3/26 @ 11 o'clock = 1 month;
	// 3/26 -> 4/26 @ 11 o'clock = overshoot by 1 hour
	// 	=> 1 month
	// 	+ 5 days remaining in march
	// 	+ 25 days till midnight of the 26th
	// => 
	// 	+ 23 hours till 10 o'clock
	makeDate(2014, 2, 26, 11),
	makeDate(2014, 4, 26, 10),
	{y:0, mo:1, d:30, h:23, m:0, s:0, note:"spans daylight savings -1 hour"}
);


// Crosses a year - negative month, positive day  ( thanks Cor )
// 
process(
	// 8/10/2014 -> 3/10/2015 = 7 months
	// 3/10/2015 -> 3/25/2015 = 15 days
	makeDate(2014, 8, 10),
	makeDate(2015, 3, 25),
	{y:0, mo:7, d:15, h:0, m:0, s:0, note:"Cor"}
);

// Crosses a year - same month, positive day ( thanks Werner )
process(
	// 9/3 -> 9/28 = 12 months
	// 25 days
	makeDate(2014, 9, 3),
	makeDate(2015, 9, 28),
	{y:1, mo:0, d:25, h:0, m:0, s:0, note:"Werner"}
);



</script>

</body>
</html>